home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / hardware / summa / io / idev.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  27.3 KB  |  1,076 lines

  1. /*
  2.  * Copyright (C) 1990, 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #ident "$Revision: 1.8 $"
  18.  
  19. #ifdef INPUT_TEST
  20. #define _KERNEL
  21. #include <sys/types.h>
  22. #undef _KERNEL
  23. #endif
  24. #include <sys/errno.h>
  25. #include <sys/cmn_err.h>
  26. #include <sys/param.h>
  27. #include <sys/kmem.h>
  28.  
  29. #include <sys/ioctl.h>
  30. #include <sys/termio.h>
  31. #include <sys/debug.h>
  32.  
  33. /* Streams stuff */
  34. #include <sys/stream.h>
  35. #include <sys/stropts.h>
  36.  
  37. /* input device stuff */
  38. #ifdef INPUT_TEST
  39. #define _KERNEL
  40. #include "inputtest.h"
  41. #endif
  42. #include <sys/shmiq.h>
  43. #include <sys/idev.h>
  44.  
  45. #include <sys/ddi.h>
  46.  
  47. #ifndef NULL
  48. #define NULL 0
  49. #endif
  50.  
  51. /***====================================================================***/
  52.  
  53. /*
  54.  * Implementation of "mousewarp" plus.
  55.  *    Solve the curve :
  56.  *        delta * ( delta - inflection ) * ( MAXRAWDELTA - delta )
  57.  *    where the result is negative below the inflection point and
  58.  *    positive above it.
  59.  *
  60.  *    cookedDelta = CONST1 * rawDelta + CONST2 * curveDelta
  61.  *
  62.  *    If greater than the threshold: Readjust
  63.  *        cookedDelta +=
  64.  *        ( ( cookedDelta - threshold ) * acceleratorN ) / acceleratorD
  65.  *
  66.  */
  67.  
  68. #define MAXRAWDELTA 254 /* abs. value of the sum of two signed char's */
  69.  
  70. /* delta must be >= -254 <= 254 !! */
  71. static int
  72. adjustDelta( idevTransform *pAccel, int delta, int applyCurve )
  73. {
  74.     register int sum ;
  75.     register int sign ;
  76.     register int accelerated ;
  77.  
  78.     sign = 0 ;
  79.     if ( delta < 0 ) {
  80.         sign = 1 ;
  81.         delta = - delta ;
  82.     }
  83.  
  84.     if ( applyCurve ) {
  85.         sum = ( pAccel->m1 * delta ) << 4 ;
  86.         if ( pAccel->cM )
  87.             sum += ( (int)  ( pAccel->cM * (int) delta
  88.                 * ( (int) delta - pAccel->inflection )
  89.                 * ( MAXRAWDELTA - (int) delta ) ) ) >> 12 ;
  90.     }
  91.     else sum = (delta << 8);
  92.  
  93.     /* here sum is represented as fixed-point 8.8 */
  94.     /* We keep the curve continuous by applying the acceleration
  95.      * to only the part of delta above the threshold
  96.      */
  97.     if ( pAccel->numerator
  98.       && ( accelerated = sum - ( pAccel->threshold << 8 ) ) > 0 ) {
  99.         accelerated *= pAccel->numerator;
  100.         accelerated /= pAccel->denominator ;
  101.         sum = (pAccel->threshold<<8)+accelerated ;
  102.     }
  103.     sum= (sum+128)>>8;
  104.     return sign ? -sum : sum ; /* New Delta */
  105. }
  106.  
  107. /***====================================================================***/
  108.  
  109. static int
  110. idevTransformCoord(idevTransform *pTrans, int pos, int last, 
  111.                 int minVal, int maxVal, unsigned flags)
  112. {
  113.     if ((pTrans->which&IDEV_ACCEL)&&(!(flags&IDEV_NO_TRANSFORM))) {
  114.         if (flags&IDEV_VALS_ABSOLUTE)
  115.             pos-= last;
  116.         pos= adjustDelta( pTrans, pos, (pTrans->which&IDEV_CURVE) );
  117.         if (pTrans->flags&IDEV_INVERT)
  118.             pos*= -1;
  119.         pos+= last;
  120.     }
  121.     else {
  122.         if (!(flags&IDEV_VALS_ABSOLUTE))
  123.             pos+= last;
  124.         if ((pTrans->which&IDEV_SCALE)&&(!(flags&IDEV_NO_TRANSFORM))) {
  125.             pos*= pTrans->numerator;
  126.             pos/= pTrans->denominator;
  127.             if (pTrans->flags&IDEV_INVERT)
  128.                 pos= (maxVal-minVal)-(pos-minVal)+minVal;
  129.         }
  130.     }
  131.     return pos;
  132. }
  133.  
  134. /***====================================================================***/
  135.  
  136. int
  137. idevGenPtrEvent(idevInfo        *pInfo,
  138.          idevValuatorState     *vNew,
  139.          unsigned          flags)
  140. {
  141. int    ptrFlags= 0;
  142. int    pos;
  143. register idevPtrInfo    *ptrInfo= &pInfo->pInfo;
  144.  
  145.     if (idevValInState(vNew,ptrInfo->xAxis)
  146.                     &&(pInfo->vInfo.mode&IDEV_GEN_PTR_X)) {
  147.     pos= vNew->value[ptrInfo->xAxis-vNew->firstValuator];
  148.     pos= idevTransformCoord(&ptrInfo->xTransform,pos,ptrInfo->x,
  149.                     ptrInfo->minX,ptrInfo->maxX,flags);
  150.     /* at this point, pos must be an absolute coordinate */
  151.     if (pos<ptrInfo->minX) {
  152.         pos= ptrInfo->minX;
  153.         ptrFlags|= QE_X_CLAMPED;
  154.     }
  155.     else if (pos>ptrInfo->maxX) {
  156.         pos= ptrInfo->maxX;
  157.         ptrFlags|= QE_X_CLAMPED;
  158.     }
  159.     if ((pos!=ptrInfo->x)||(flags&(QE_RESPONSE|IDEV_FORCE_EVENT))||
  160.                 (ptrFlags&QE_X_CLAMPED)) {
  161.        ptrInfo->x= pos;
  162.        ptrFlags|= IDEV_GEN_PTR_X;
  163.     }
  164.     else ptrFlags&= (~QE_X_CLAMPED);
  165.     }
  166.     if (idevValInState(vNew,ptrInfo->yAxis)
  167.                     &&(pInfo->vInfo.mode&IDEV_GEN_PTR_Y)) {
  168.     pos= vNew->value[ptrInfo->yAxis-vNew->firstValuator];
  169.     pos= idevTransformCoord(&ptrInfo->yTransform,pos,ptrInfo->y,
  170.                     ptrInfo->minY,ptrInfo->maxY,flags);
  171.     if (pos<ptrInfo->minY) {
  172.         pos= ptrInfo->minY;
  173.         ptrFlags|= QE_Y_CLAMPED;
  174.     }
  175.     else if (pos>ptrInfo->maxY) {
  176.         pos= ptrInfo->maxY;
  177.         ptrFlags|= QE_Y_CLAMPED;
  178.     }
  179.     if ((pos!=ptrInfo->y)||(flags&(QE_RESPONSE|IDEV_FORCE_EVENT))||
  180.                 (ptrFlags&QE_Y_CLAMPED))
  181.     {
  182.        ptrInfo->y= pos;
  183.        ptrFlags|= IDEV_GEN_PTR_Y;
  184.     }
  185.     else ptrFlags&= (~QE_Y_CLAMPED);
  186.     }
  187.     if (ptrFlags && !(flags&IDEV_SILENT)) {
  188.     mblk_t                *mbp;
  189.     register struct shmqevent    *msg;
  190.     if (!(mbp=allocb(sizeof(struct shmqevent),BPRI_MED))){
  191.         cmn_err( CE_WARN, "Couldn't allocate streams buffer -- valuator events lost\n");
  192.         return(0); /* just pitch valuator events */
  193.     }
  194.     msg = (struct shmqevent *) mbp->b_wptr;
  195.     msg->un.id.devminor=    pInfo->sInfo.shmiqid.devminor;
  196.     msg->un.id.index=     pInfo->sInfo.shmiqid.index;
  197.     msg->data.device=     pInfo->sInfo.shmiqid.index;
  198.     msg->data.type=        QE_PTR_EVENT;
  199.     msg->data.which=    0;
  200.     msg->data.un.ptraxis[0]=ptrInfo->x;
  201.     msg->data.un.ptraxis[1]=ptrInfo->y;
  202.     msg->data.flags=    (flags&QE_RESPONSE)|ptrFlags;
  203.     mbp->b_wptr+=    sizeof (struct shmqevent);
  204.     putnext( pInfo->sInfo.rq, mbp );
  205.     }
  206.     return 1;
  207. }
  208.  
  209.  
  210. /***====================================================================***/
  211.  
  212. int
  213. idevGenValEvents(idevInfo        *pInfo,
  214.          idevValuatorState     *vNew,
  215.          unsigned          flags)
  216. {
  217. mblk_t                *mbp;
  218. register struct shmqevent    *msg;
  219. int                 i,eventCnt;
  220. int                 ndx,pos;
  221. int                 rtrn= 1;
  222. int                 clamped;
  223.  
  224.     if ((vNew->nValuators<1)
  225.         ||(vNew->firstValuator+vNew->nValuators>pInfo->vInfo.nVal))
  226.         
  227.         return 0;
  228.     if (pInfo->vInfo.mode&IDEV_GEN_PTR_EVENTS) 
  229.         rtrn|= idevGenPtrEvent(pInfo,vNew,flags);
  230.     if (pInfo->vInfo.mode&IDEV_GEN_NON_PTR_EVENTS && !(flags&IDEV_SILENT)) {
  231.         /* Get a message buffer to send upstream */
  232.         if (!(mbp=allocb(vNew->nValuators*sizeof(struct shmqevent),
  233.                                 BPRI_MED))){
  234.             cmn_err( CE_WARN, "Couldn't allocate streams buffer -- valuator events lost\n");
  235.         }
  236.         else msg = (struct shmqevent *) mbp->b_wptr;
  237.     }
  238.     else mbp= NULL;
  239.  
  240.     ndx= vNew->firstValuator;
  241.     for (eventCnt=i=0;i<vNew->nValuators;i++,ndx++) {
  242.         pos= idevTransformCoord(&pInfo->vInfo.transform[ndx],
  243.                     vNew->value[i],
  244.                     pInfo->vInfo.sysValue[ndx],
  245.                     pInfo->vInfo.desc[ndx].minVal,
  246.                     pInfo->vInfo.desc[ndx].maxVal,
  247.                     flags);
  248.         if ((pos==pInfo->vInfo.sysValue[ndx])
  249.                 &&(!(flags&(QE_RESPONSE|IDEV_FORCE_EVENT))))
  250.             continue;
  251.  
  252.         else if (pos<pInfo->vInfo.desc[ndx].minVal) {
  253.             clamped = QE_CLAMPED;
  254.             rtrn |=    QE_CLAMPED;
  255.             pos = pInfo->vInfo.desc[ndx].minVal;
  256.         }
  257.         else if (pos>pInfo->vInfo.desc[ndx].maxVal) {
  258.             clamped = QE_CLAMPED;
  259.             rtrn |= QE_CLAMPED;
  260.             pos = pInfo->vInfo.desc[ndx].maxVal;
  261.         }
  262.         else
  263.             clamped = 0;
  264.  
  265.         pInfo->vInfo.sysValue[ndx] = pos;
  266.  
  267.         if (mbp&&(idevNth(pInfo->vInfo.active,ndx))) {
  268.             msg->un.id.devminor = pInfo->sInfo.shmiqid.devminor;
  269.             msg->un.id.index = pInfo->sInfo.shmiqid.index;
  270.             msg->data.device = pInfo->sInfo.shmiqid.index;
  271.             msg->data.type = QE_VAL_EVENT;
  272.             msg->data.which = ndx;
  273.             msg->data.flags = (flags|QE_MORE_EVENTS|clamped)&0xff;
  274.             msg->data.un.pos = pos;
  275.             eventCnt++;
  276.             msg++;
  277.         }
  278.     }
  279.  
  280.     if (mbp) {
  281.         if (eventCnt>0) {
  282.             if (!(flags&QE_MORE_EVENTS))
  283.                 (--msg)->data.flags &= (~QE_MORE_EVENTS);
  284.  
  285.             mbp->b_wptr += sizeof (struct shmqevent)*eventCnt;
  286.             putnext( pInfo->sInfo.rq, mbp );
  287.         }
  288.         else {
  289.             freemsg(mbp);
  290.         }
  291.     }
  292.     return(rtrn);
  293. }
  294.  
  295. /***====================================================================***/
  296.  
  297. int
  298. idevGenValEvent(idevInfo    *pInfo,
  299.         int         axis,
  300.         int         value,
  301.         unsigned     flags)
  302. {
  303. idevValuatorState    new;
  304. mblk_t                *mbp;
  305. register struct shmqevent    *msg;
  306. int                 rtrn= 1;
  307. idevValInfo            *pVInfo;
  308.  
  309.     /* make sure axis is legal and active */
  310.     if ((axis<0)||(axis>=pInfo->vInfo.nVal))
  311.     return 0;
  312.     new.firstValuator = axis;
  313.     new.nValuators = 1;
  314.     new.value[0] = value;
  315.     return idevGenValEvents(pInfo,&new,flags);
  316. }
  317.  
  318. /***====================================================================***/
  319.  
  320. int
  321. idevGetValDesc(idevInfo *pInfo, idevGetSetValDesc *axis)
  322. {
  323.     if (axis->valNum<pInfo->vInfo.nVal) {
  324.     axis->desc=    pInfo->vInfo.desc[axis->valNum];
  325.     return 1;
  326.     }
  327.     return 0;
  328. }
  329.  
  330. /***====================================================================***/
  331.  
  332. /* Parameters for "Warp" */
  333. #define MAXRAWDELTA 254 /* abs. value of the sum of two signed char's */
  334. /* defaults -- totally arbitrary, my choice */
  335. #define DFLT_MULTIPLIER 16
  336. #define DFLT_CRVFACT 16
  337. #define DFLT_INFLECTION ( MAXRAWDELTA / 3 )
  338. /* default acceleration == ~2.7 above 8 */
  339. #define DFLT_THRESHOLD 8
  340. #define DFLT_ACCELERATORN 8
  341. #define DFLT_ACCELERATORD 3
  342.  
  343. idevTransform idevDfltAccel = {
  344.     IDEV_ACCEL,
  345.     IDEV_ACCEL,
  346.     0,
  347.     DFLT_ACCELERATORN,
  348.     DFLT_ACCELERATORD,
  349.     DFLT_MULTIPLIER,
  350.     DFLT_CRVFACT,
  351.     DFLT_INFLECTION,
  352.     DFLT_THRESHOLD
  353. };
  354.  
  355. idevTransform idevDfltScale = {
  356.     IDEV_SCALE,
  357.     IDEV_SCALE,
  358.     0,
  359.     1, 1
  360. };
  361.  
  362.  
  363. static int
  364. idevCopyTransform(unsigned which,idevTransform *old,idevTransform *new)
  365. {
  366.  
  367.     if (which&IDEV_VT_SET_TRANSFORM) {
  368.         if (new->which) {
  369.             if (new->which&old->possible) {
  370.             old->which= (new->which&old->possible);
  371.             }
  372.             else {
  373.             return 0;
  374.             }
  375.         }
  376.         else old->which= 0;
  377.     }
  378.     if (which&IDEV_VT_SET_FLAGS) {
  379.         old->flags= new->flags;
  380.     }
  381.     if (which&IDEV_VT_SET_NUMERATOR) {
  382.         old->numerator = new->numerator;
  383.     }
  384.     if (which&IDEV_VT_SET_DENOMINATOR) {
  385.         if (new->denominator==0)
  386.             old->denominator = 1;
  387.         else    old->denominator = new->denominator;
  388.     }
  389.     if (which&IDEV_PC_SET_THRESHOLD) {
  390.         old->threshold = new->threshold;
  391.     }
  392.     if (which&IDEV_PC_SET_MULTIPLIER) {
  393.         if ( new->m1 > 0xFF )
  394.             old->m1 = 0xFF;
  395.         else if ( new->m1 <= 0 )
  396.             old->m1 = DFLT_MULTIPLIER;
  397.         else    old->m1 = new->m1;
  398.     }
  399.     if (which&IDEV_PC_SET_CURVE_FACTOR) {
  400.         if ( new->cM > 0xFF )
  401.             old->cM = 0xff;
  402.         else if ( new->cM < 0 )
  403.             old->cM = DFLT_CRVFACT;
  404.         else    old->cM = new->cM;
  405.     }
  406.     if (which&IDEV_PC_SET_CURVE_INFLECTION) {
  407.         if ( new->inflection < 0 )
  408.             old->inflection = MAXRAWDELTA / 2;
  409.         else if ( new->inflection >= MAXRAWDELTA )
  410.             old->inflection = MAXRAWDELTA - 1;
  411.         else    old->inflection = new->inflection;
  412.     }
  413.     return 1;
  414. }
  415.  
  416. /***====================================================================***/
  417.  
  418. int
  419. idevSetPtrCtrl(idevInfo *pInfo,idevPtrControl *ctrl)
  420. {
  421. idevTransform    *pXAccel= &pInfo->pInfo.xTransform;
  422. idevTransform    *pYAccel= &pInfo->pInfo.yTransform;
  423.  
  424.     if (ctrl->which&IDEV_PC_SET_ACCEL_N) {
  425.         pXAccel->numerator = ctrl->accelNumerator;
  426.         pYAccel->numerator = ctrl->accelNumerator;
  427.     }
  428.     if (ctrl->which&IDEV_PC_SET_ACCEL_D) {
  429.         register int d= ctrl->accelDenominator;
  430.         if (d==0)
  431.             d = 1;
  432.         pXAccel->denominator = pYAccel->denominator = d;
  433.     }
  434.     if (ctrl->which&IDEV_PC_SET_THRESHOLD) {
  435.         pXAccel->threshold = ctrl->threshold;
  436.         pYAccel->threshold = ctrl->threshold;
  437.     }
  438.     if (ctrl->which&IDEV_PC_SET_MULTIPLIER) {
  439.         register int m = ctrl->mult;
  440.         if ( m > 0xFF )
  441.             m = 0xFF;
  442.         else if ( m <= 0 )
  443.             m = DFLT_MULTIPLIER;
  444.         pXAccel->m1 = pYAccel->m1= m;
  445.     }
  446.     if (ctrl->which&IDEV_PC_SET_CURVE_FACTOR) {
  447.         register int c = ctrl->curveFactor;
  448.         if ( c > 0xFF )
  449.             c = 0xff;
  450.         else if ( c < 0 )
  451.             c = DFLT_CRVFACT;
  452.         pXAccel->cM = pYAccel->cM = c;
  453.     }
  454.     if (ctrl->which&IDEV_PC_SET_CURVE_INFLECTION) {
  455.         register int c = ctrl->curveInflection;
  456.         if ( c < 0 )
  457.             c = MAXRAWDELTA / 2;
  458.         else if ( c >= MAXRAWDELTA )
  459.             c = MAXRAWDELTA - 1;
  460.         pXAccel->inflection = pYAccel->inflection = c;
  461.     }
  462.     return 1;
  463. }
  464.  
  465. /***====================================================================***/
  466.  
  467. int
  468. idevGetTransform(idevInfo *pInfo,idevGetSetTransform *trans)
  469. {
  470.     if (trans->which&IDEV_VT_PTR_X) {
  471.         trans->transform= pInfo->pInfo.xTransform;
  472.         return 1;
  473.     }
  474.     if (trans->which&IDEV_VT_PTR_Y) {
  475.         trans->transform= pInfo->pInfo.yTransform;
  476.         return 1;
  477.     }
  478.     if (trans->valNum<pInfo->vInfo.nVal) {
  479.         trans->transform= pInfo->vInfo.transform[trans->valNum];
  480.         return 1;
  481.     }
  482.     return 0;
  483. }
  484.  
  485.  
  486. /***====================================================================***/
  487.  
  488. int
  489. idevSetTransform(idevInfo *pInfo,idevGetSetTransform *set)
  490. {
  491. unsigned which = set->which;
  492.  
  493.     if ((which&IDEV_VT_SET_PTR_AND_VAL)&&(!(which&IDEV_VT_SET_PTR))) {
  494.         if (set->valNum==pInfo->pInfo.xAxis)
  495.             which|= IDEV_VT_PTR_X;
  496.         if (set->valNum==pInfo->pInfo.yAxis)
  497.             which|= IDEV_VT_PTR_Y;
  498.     }
  499.     if (which&IDEV_VT_PTR_X) {
  500.         idevCopyTransform(which,&pInfo->pInfo.xTransform,
  501.                         &set->transform);
  502.         if ((which&IDEV_VT_SET_PTR_AND_VAL)
  503.                 &&(pInfo->pInfo.xAxis<pInfo->vInfo.nVal)) {
  504.             idevCopyTransform(which,
  505.                   &pInfo->vInfo.transform[pInfo->pInfo.xAxis],
  506.                   &set->transform);
  507.         }
  508.     }
  509.     if (which&IDEV_VT_PTR_Y) {
  510.         idevCopyTransform(which,&pInfo->pInfo.yTransform,
  511.                         &set->transform);
  512.         if ((which&IDEV_VT_SET_PTR_AND_VAL)
  513.                 &&(pInfo->pInfo.yAxis<pInfo->vInfo.nVal)) {
  514.             idevCopyTransform(which,
  515.                   &pInfo->vInfo.transform[pInfo->pInfo.yAxis],
  516.                   &set->transform);
  517.         }
  518.     }
  519.     if (which&IDEV_VT_SET_PTR)
  520.         return 1;
  521.     if (set->valNum<pInfo->vInfo.nVal) {
  522.         idevCopyTransform(which,&pInfo->vInfo.transform[set->valNum],
  523.                          &set->transform);
  524.         return 1;
  525.     }
  526.     return 0;
  527. }
  528.  
  529.  
  530. /***====================================================================***/
  531.  
  532. /* ARGSUSED */
  533. int
  534. idevSetValDesc(idevInfo *pInfo,idevGetSetValDesc *new)
  535. {
  536. int            count,i;
  537. idevValuatorDesc    *old;
  538. int            *pOldValue;
  539. idevValInfo         *pVInfo= &pInfo->vInfo;
  540.  
  541.     if (new->valNum>=pVInfo->nVal)
  542.     return 0;
  543.  
  544.     if (new->flags&IDEV_SAME) {
  545.     new->valNum=    0;
  546.     old=        &pVInfo->desc[0];
  547.     pOldValue=    &pVInfo->sysValue[0];
  548.     count=        pVInfo->nVal;
  549.     }
  550.     else {
  551.     old=        &pVInfo->desc[new->valNum];
  552.     pOldValue=    &pVInfo->sysValue[new->valNum];
  553.     count=        1;
  554.     }
  555.  
  556.     for (i=0;i<count;i++,old++) {
  557.     if (new->flags&IDEV_SET_MIN) {
  558.         old->minVal=    new->desc.minVal;
  559.         if (old->minVal<old->hwMinVal)
  560.         old->minVal=    old->hwMinVal;
  561.         if ((*pOldValue)<old->minVal) {
  562.         (*pOldValue)=    old->minVal;
  563.         idevGenValEvent(pInfo,i+new->valNum,old->minVal,
  564.                         QE_CLAMPED|QE_RESPONSE);
  565.         }
  566.     }
  567.     if (new->flags&IDEV_SET_MAX) {
  568.         old->maxVal=    new->desc.maxVal;
  569.         if (old->maxVal>old->hwMaxVal) 
  570.         old->maxVal=    old->hwMaxVal;
  571.         if ((*pOldValue)>old->maxVal) {
  572.         (*pOldValue)= old->maxVal;
  573.         idevGenValEvent(pInfo,i+new->valNum,old->maxVal,
  574.                         QE_RESPONSE|QE_CLAMPED);
  575.         }
  576.         if ((pInfo->pInfo.maxX==0)&&(i+new->valNum==pInfo->pInfo.xAxis)) {
  577.         pInfo->pInfo.minX= old->minVal;
  578.         pInfo->pInfo.maxX= old->maxVal;
  579.         }
  580.         else if ((pInfo->pInfo.maxY==0)
  581.                     &&(i+new->valNum==pInfo->pInfo.yAxis)) {
  582.         pInfo->pInfo.minY= old->minVal;
  583.         pInfo->pInfo.maxY= old->maxVal;
  584.         }
  585.     }
  586.     if (new->flags&IDEV_SET_RESOLUTION) {
  587.         old->resolution=    new->desc.resolution;
  588.         if (old->resolution<old->hwMinRes)
  589.          old->resolution= old->hwMinRes;
  590.         else if (old->resolution>old->hwMaxRes)
  591.          old->resolution= old->hwMaxRes;
  592.     }
  593.     }
  594.     return(1);
  595. }
  596.  
  597. /***====================================================================***/
  598.  
  599. /* ARGSUSED */
  600. int
  601. idevGetValState(idevInfo *pInfo,register idevValuatorState *vals)
  602. {
  603.     if ((vals->firstValuator+vals->nValuators<pInfo->vInfo.nVal)&&
  604.     (vals->nValuators<=IDEV_VALUATOR_STATE_MAX)) {
  605.     bcopy(&pInfo->vInfo.sysValue[vals->firstValuator],vals->value,
  606.         4*vals->nValuators);
  607.     return 1;
  608.     }
  609.     return 0;
  610. }
  611.  
  612. /***====================================================================***/
  613.  
  614.     /*
  615.      * Passes a button event upstream (presumably to the shared
  616.      * memory queue).
  617.      */
  618.  
  619. int
  620. idevGenBtnEvent( idevInfo *pInfo, unsigned btnNum, int flags)
  621. {
  622. register struct shmqevent    *msg;
  623. int                 eventcount= 0;
  624. mblk_t                *mbp;
  625. unsigned             mask,offset;
  626.  
  627.  
  628.     mask = idevMask(btnNum);
  629.     offset = idevOffset(btnNum);
  630.  
  631.     if ( pInfo->bInfo.state[offset] & mask ) {
  632.     if (flags&IDEV_BTN_PRESS) {
  633.         if (flags&IDEV_FAKE_EVENT)
  634.         eventcount = 2;
  635.         else if (flags&IDEV_FORCE_EVENT)
  636.         eventcount = 1;
  637.         else eventcount = 0;
  638.     }
  639.     else eventcount = 1;
  640.     }
  641.     else  if (!(flags&IDEV_BTN_PRESS)) {
  642.     if (flags&IDEV_FAKE_EVENT)
  643.         eventcount = 2;
  644.     else if (flags&IDEV_FORCE_EVENT)
  645.         eventcount = 1;
  646.     else eventcount = 0;
  647.     }
  648.     else eventcount = 1;
  649.  
  650.     if (flags&IDEV_BTN_PRESS)    pInfo->bInfo.state[offset] |= mask;
  651.     else            pInfo->bInfo.state[offset] &= ~mask;
  652.  
  653.     if ((!(pInfo->bInfo.active[offset]&mask))||eventcount<1) {
  654.     return(0);
  655.     }
  656.  
  657.     if (!(mbp=allocb(eventcount*sizeof(struct shmqevent), BPRI_MED))) {
  658.     cmn_err( CE_WARN,"Couldn't allocate streams buffer -- button event lost.\n" );
  659.     return(0); /* just pitch button events */
  660.     }
  661.     msg = (struct shmqevent *) mbp->b_wptr ;
  662.  
  663.     if (eventcount>1) {
  664.     msg->un.id.devminor=    pInfo->sInfo.shmiqid.devminor;
  665.     msg->un.id.index=    pInfo->sInfo.shmiqid.index;
  666.     msg->data.device=    pInfo->sInfo.shmiqid.index;
  667.     msg->data.type=        QE_BTN_EVENT;
  668.     msg->data.which=    btnNum;
  669.     msg->data.flags=    (flags&IDEV_BTN_PRESS?0:QE_BTN_DOWN);
  670.     msg++;
  671.     }
  672.     msg->un.id.devminor=    pInfo->sInfo.shmiqid.devminor;
  673.     msg->un.id.index=        pInfo->sInfo.shmiqid.index;
  674.     msg->data.device=        pInfo->sInfo.shmiqid.index;
  675.     msg->data.type=        QE_BTN_EVENT;
  676.     msg->data.which=        btnNum;
  677.     msg->data.flags=        (flags&IDEV_BTN_PRESS?QE_BTN_DOWN:0);
  678.  
  679.     mbp->b_wptr += eventcount*sizeof (struct shmqevent) ;
  680.     putnext( pInfo->sInfo.rq, mbp ) ;
  681.     return(eventcount);
  682. }
  683.  
  684. /***====================================================================***/
  685.  
  686.     /*
  687.      * Passes button events upstream (presumably to the shared
  688.      * memory queue).
  689.      */
  690.  
  691. unsigned char leftmask[8]= {
  692.     0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f
  693. };
  694. int
  695. idevGenBtnEvents( idevInfo *pInfo, unsigned char *newMask,
  696.                     unsigned char *newState)
  697. {
  698. register struct shmqevent    *msg;
  699. mblk_t                *mbp;
  700. register int byte,bit;
  701. unsigned char    changed,mask;
  702. int        events= 0;
  703.  
  704.     newMask[idevSize(pInfo->bInfo.nBtn)-1]&= leftmask[pInfo->bInfo.nBtn&0x7];
  705.     for (byte=0;byte<idevSize(pInfo->bInfo.nBtn);byte++) {
  706.     changed= (pInfo->bInfo.state[byte]^newState[byte])&(newMask[byte]);
  707.     if (changed) {
  708.         for (mask=1,bit=0;(bit<8)&&changed;bit++,mask<<=1) {
  709.         if (changed&pInfo->bInfo.active[byte]&mask) {
  710.             changed&= ~mask;
  711.             if (mbp=allocb(sizeof(struct shmqevent),BPRI_MED)) {
  712.             msg = (struct shmqevent *) mbp->b_wptr ;
  713.  
  714.             msg->un.id.devminor = pInfo->sInfo.shmiqid.devminor;
  715.             msg->un.id.index = pInfo->sInfo.shmiqid.index;
  716.             msg->data.device = pInfo->sInfo.shmiqid.index;
  717.             msg->data.type = QE_BTN_EVENT;
  718.             msg->data.which = (byte<<3)+bit;
  719.             msg->data.flags = ( newState[byte] & mask 
  720.                 ? IDEV_BTN_PRESS
  721.                 : 0 );
  722.             mbp->b_wptr += sizeof (struct shmqevent);
  723.             putnext( pInfo->sInfo.rq, mbp );
  724.             events++;
  725.             }
  726.             else {
  727.             cmn_err(CE_WARN,"Couldn't allocate streams buffer -- button event lost.\n");
  728.             continue;
  729.             }
  730.         }
  731.         }
  732.         pInfo->bInfo.state[byte]&=    ~newMask[byte];
  733.         pInfo->bInfo.state[byte]|=    (newState[byte]&newMask[byte]);
  734.     }
  735.     }
  736.     return events;
  737. }
  738.  
  739. /***====================================================================***/
  740.  
  741. int
  742. idevSetPtrMode(idevInfo *pInfo,idevPtrMode *pMode)
  743. {
  744. int    rtrn= 1;
  745.  
  746.     if (pMode->mode&IDEV_GEN_PTR_EVENTS) {
  747.     if (pMode->mode&IDEV_GEN_PTR_X) {
  748.         if ((pMode->xAxis>=pInfo->vInfo.nVal)||(pMode->xAxis<0))
  749.         rtrn= 0;
  750.         else {
  751.         pInfo->pInfo.xAxis= pMode->xAxis;
  752.         if (pInfo->pInfo.minX==pInfo->pInfo.maxX) {
  753.             pInfo->pInfo.minX= pInfo->vInfo.desc[pMode->xAxis].minVal;
  754.             pInfo->pInfo.maxX= pInfo->vInfo.desc[pMode->xAxis].maxVal;
  755.         }
  756.         }
  757.     }
  758.     if (pMode->mode&IDEV_GEN_PTR_Y) {
  759.         if ((pMode->yAxis>=pInfo->vInfo.nVal)||(pMode->xAxis<0))
  760.         rtrn= 0;
  761.         else {
  762.         pInfo->pInfo.yAxis= pMode->yAxis;
  763.         if (pInfo->pInfo.minY==pInfo->pInfo.maxY) {
  764.             pInfo->pInfo.minY= pInfo->vInfo.desc[pMode->yAxis].minVal;
  765.             pInfo->pInfo.maxY= pInfo->vInfo.desc[pMode->yAxis].maxVal;
  766.         }
  767.         }
  768.     }
  769.     }
  770.     else {
  771.     pInfo->pInfo.xAxis= pInfo->pInfo.yAxis= -1;
  772.     }
  773.     pInfo->vInfo.mode=    pMode->mode;
  774.     return rtrn;
  775. }
  776.  
  777. /***====================================================================***/
  778.  
  779. int
  780. idevSetPtrBounds(idevInfo *pInfo,idevPtrBounds *pBounds)
  781. {
  782. int    rtrn= 1;
  783.  
  784.     if (pBounds->which&IDEV_PB_SET_MIN_X) {
  785.     if (pBounds->minX>0)
  786.         pInfo->pInfo.minX= pBounds->minX;
  787.     else    pInfo->pInfo.minX= 0;
  788.     }
  789.     if (pBounds->which&IDEV_PB_SET_MAX_X) {
  790.     if (pBounds->maxX>pBounds->minX)
  791.         pInfo->pInfo.maxX= pBounds->maxX;
  792.     else    pInfo->pInfo.maxX= pBounds->minX;
  793.     }
  794.     if (pBounds->which&IDEV_PB_SET_MIN_Y) {
  795.     if (pBounds->minY>0)
  796.         pInfo->pInfo.minY= pBounds->minY;
  797.     else    pInfo->pInfo.minY= 0;
  798.     }
  799.     if (pBounds->which&IDEV_PB_SET_MAX_Y) {
  800.     if (pBounds->maxY>pBounds->minY)
  801.         pInfo->pInfo.maxY= pBounds->maxY;
  802.     else    pInfo->pInfo.maxY= pBounds->minY;
  803.     }
  804.     return 1;
  805. }
  806.  
  807. /***====================================================================***/
  808.  
  809. int
  810. idevSetPtr(idevInfo *pInfo,idevPtrVals *pVals)
  811. {
  812. int    rtrn= 1;
  813. idevValuatorState new;
  814. int loudness;
  815.  
  816.     /*
  817.      * >NEW< IDEV_SILENT says don't generate an event no matter what,
  818.      * just process the valuator change and be quiet about it!  Shush. -mjk
  819.      *
  820.      * Before this, pointers were echoing back the location (twice!)
  821.      * when the X server warped the pointer.
  822.      */
  823.     if(pVals->which&IDEV_SILENT) {
  824.        loudness = IDEV_SILENT;
  825.     } else {
  826.        loudness = 0;
  827.     }
  828.     new.nValuators = 1;
  829.     new.firstValuator = pInfo->pInfo.xAxis;
  830.     new.value[0] = pVals->x;
  831.     if (pVals->which&IDEV_PTR_SET_X_VAL) {
  832.     rtrn= idevGenValEvents(pInfo,&new,
  833.        IDEV_VALS_ABSOLUTE|IDEV_NO_TRANSFORM|loudness) &&rtrn;
  834.     }
  835.     else if (pVals->which&IDEV_PTR_SET_X) {
  836.     rtrn= idevGenPtrEvent(pInfo,&new,
  837.        IDEV_VALS_ABSOLUTE|IDEV_NO_TRANSFORM|loudness) &&rtrn;
  838.     }
  839.     new.nValuators = 1;
  840.     new.firstValuator = pInfo->pInfo.yAxis;
  841.     new.value[0] = pVals->y;
  842.     if (pVals->which&IDEV_PTR_SET_Y_VAL) {
  843.     rtrn= idevGenValEvents(pInfo,&new,
  844.        IDEV_VALS_ABSOLUTE|IDEV_NO_TRANSFORM|loudness) &&rtrn;
  845.     }
  846.     else if (pVals->which&IDEV_PTR_SET_Y) {
  847.     rtrn= idevGenPtrEvent(pInfo,&new,
  848.        IDEV_VALS_ABSOLUTE|IDEV_NO_TRANSFORM|loudness) &&rtrn;
  849.     }
  850.     return rtrn;
  851. }
  852.  
  853. /***====================================================================***/
  854.  
  855. int
  856. idevUpdateBitArray(int nBytes,char *old, register idevBitVals *new)
  857. {
  858.     register int i;
  859.  
  860.     for (i=nBytes-1; i>=0; i-- ) {
  861.         old[i] &= ~new->mask[i];
  862.         old[i] |= (new->mask[i]&new->value[i]);
  863.     }
  864.     return 1;
  865. }
  866.  
  867. /***====================================================================***/
  868.  
  869. static struct termio idevDfltLineSettings = {
  870.     IGNBRK|IGNPAR,    /* c_iflag */
  871.     0,        /* c_oflag */
  872.     B9600|CS8|CREAD, /* c_cflag */
  873.     0,            /* c_lflag */
  874.     LDISC1,            /* c_line */
  875.     /* VINTR VQUIT VERASE VKILL VEOF VMIN VTIME VSWTCH */
  876.     {      0,    0,     0,    0,   0,   3,    1,     0  }
  877. };
  878.  
  879. int
  880. idevChangeLineSettings(idevInfo *pInfo,struct termio *tio)
  881. {
  882. mblk_t    *iob;
  883. struct iocblk    *iocb;
  884.  
  885.     iob = allocb( sizeof(struct iocblk), BPRI_MED );
  886.     if (iob==NULL) {
  887.         cmn_err(CE_WARN,"Can't allocate streams buffer for M_IOCTL. Line settings not changed.\n");
  888.         return 0;
  889.     }
  890.     iob->b_cont= allocb( sizeof(struct termio), BPRI_MED );
  891.     if (iob->b_cont==NULL) {
  892.         cmn_err(CE_WARN,"Can't allocate streams buffer for M_DATA. Line settings not changed.\n");
  893.         freemsg(iob);
  894.         return 0;
  895.     }
  896.     iob->b_datap->db_type= M_IOCTL;
  897.     iocb = (struct iocblk *)iob->b_wptr;
  898.     iob->b_wptr+= sizeof(struct iocblk);
  899.     iocb->ioc_cmd= TCSETAW;
  900. /* XXXjwag - uid and gid are now part of cred struct which hasn't
  901.  * been allocated.. but who uses this anyway??
  902.     iocb->ioc_uid= 0;
  903.     iocb->ioc_gid= 0;
  904.  */
  905.     iocb->ioc_id=  0;
  906.     iocb->ioc_count= sizeof(struct termio);
  907.     iocb->ioc_error= 0;
  908.     iocb->ioc_rval= 0;
  909.     if (tio==NULL)
  910.         tio= &idevDfltLineSettings;
  911.     *((struct termio *)iob->b_cont->b_wptr)= *tio;
  912.     iob->b_cont->b_wptr+= sizeof(struct termio);
  913.     putnext( pInfo->sInfo.wq, iob );
  914.     return 1;
  915. }
  916.  
  917. /***====================================================================***/
  918.  
  919. int
  920. idev_rput( register queue_t *rq, mblk_t *mp )
  921. {
  922.     idevInfo *info;
  923.  
  924.     info = (idevInfo *) rq->q_ptr;
  925.  
  926.     switch ( mp->b_datap->db_type ) {
  927.         case M_FLUSH:
  928.             if ( *mp->b_rptr & FLUSHR ) {
  929.                 flushq( rq, FLUSHDATA ) ;
  930.             }
  931.         break ;
  932.  
  933.         case M_DATA:
  934.         {
  935.             register mblk_t *bp;
  936.             for (bp=mp; bp!=NULL; bp= bp->b_cont) {
  937.                 (*info->sInfo.readData)( info, bp->b_rptr, 
  938.                         bp->b_wptr-bp->b_rptr);
  939.             }
  940.             freemsg( mp );
  941.             return 0;
  942.         }
  943.         default:
  944.             break ;
  945.     }
  946.     if ( queclass( mp ) > QNORM || canput( rq->q_next ) )
  947.         putnext( rq, mp );
  948.     else
  949.         freemsg(mp);
  950.     return 0;
  951. }
  952.  
  953. /***====================================================================***/
  954.  
  955. char *
  956. idev_ioctl_name(unsigned io)
  957. {
  958.     switch(io) {
  959.     case IDEVGETDEVICEDESC: return "GETDEVICEDESC";
  960.     case IDEVGETVALUATORDESC: return "GETVALUATORDESC";
  961.     case IDEVGETKEYMAPDESC: return "GETKEYMAPDESC";
  962.     case IDEVGETSTRDPYDESC: return "GETSTRDPYDESC";
  963.     case IDEVGETINTDPYDESC: return "GETINTDPYDESC";
  964.  
  965.     case IDEVGETBUTTONS: return "GETBUTTONS";
  966.     case IDEVGETVALUATORS: return "GETVALUATORS";
  967.     case IDEVGETLEDS: return "GETLEDS";
  968.     case IDEVGETSTRDPY: return "GETSTRDPY";
  969.     case IDEVGETINTDPYS: return "GETINTDPYS";
  970.     case IDEVENABLEBUTTONS: return "ENABLEBUTTONS";
  971.  
  972.     case IDEVENABLEVALUATORS: return "ENABLEVALUATORS";
  973.     case IDEVSETVALUATORS: return "SETVALUATORS";
  974.     case IDEVCHANGEVALUATORS: return "CHANGEVALUATORS";
  975.     case IDEVSETVALUATORDESC: return "SETVALUATORDESC";
  976.  
  977.     case IDEVSETLEDS: return "SETLEDS";
  978.     case IDEVSETSTRDPY: return "SETSTRDPY";
  979.     case IDEVSETINTDPYS: return "SETINTDPYS";
  980.     case IDEVRINGBELL: return "RINGBELL";
  981.  
  982.     case IDEVKEYBDCONTROL: return "KEYBDCONTROL";
  983.     case IDEVPTRCONTROL: return "PTRCONTROL";
  984.     case IDEVOTHERCONTROL: return "OTHERCONTROL";
  985.     case IDEVSETPTRMODE: return "SETPTRMODE";
  986.     case IDEVOTHERQUERY: return "OTHERQUERY";
  987.     case IDEVSETPTRBOUNDS: return "SETPTRBOUNDS";
  988.     case IDEVSETPTR    : return "SETPTR    ";
  989.  
  990.     case IDEVSETTRANSFORM: return "SETTRANSFORM";
  991.     case IDEVGETTRANSFORM: return "GETTRANSFORM";
  992.  
  993.     case IDEVINITDEVICE: return "INITDEVICE";
  994.     }
  995.     return "unknown";
  996. }
  997.  
  998. /***====================================================================***/
  999.  
  1000. int
  1001. idev_wput( register queue_t *wq, register mblk_t *mp )
  1002. {
  1003.     idevInfo *info;
  1004.     register char *stuff;
  1005.     int size;
  1006.  
  1007.     info = (idevInfo *) wq->q_ptr;
  1008.     stuff = mp->b_rptr;
  1009.     size = mp->b_wptr-mp->b_rptr;
  1010.  
  1011.     switch ( mp->b_datap->db_type ) {
  1012.         case M_PCPROTO :
  1013.             if ((mp->b_wptr-stuff==sizeof(struct shmqntc))
  1014.                  && (((struct shmqntc *)stuff )->mtype == SHMIQ_NOTICE)) {
  1015.                 info->sInfo.shmiqid.devminor =
  1016.                     ((struct shmqntc *)stuff)->id.devminor;
  1017.                 info->sInfo.shmiqid.index =
  1018.                     ((struct shmqntc *)stuff)->id.index;
  1019.                 ((struct shmqntc *)stuff)->mtype = SHMIQ_PLAY;
  1020.                 qreply( wq, mp ) ;
  1021.                 return 0;
  1022.             }
  1023.             break;
  1024.  
  1025.         case M_FLUSH:
  1026.             break;
  1027.  
  1028.         case M_IOCTL:
  1029.         {
  1030.             struct iocblk *iocp;
  1031.             int found = 0;
  1032.             mblk_t *nmp = mp->b_cont;
  1033.         
  1034.             iocp = (struct iocblk *)stuff;
  1035.  
  1036.             if (nmp == NULL)  {
  1037.                 stuff= NULL;
  1038.                 size= NULL;
  1039.             }
  1040.             else if (nmp->b_datap->db_type != M_DATA) {
  1041.                 mp->b_datap->db_type = M_IOCNAK;
  1042.                 qreply(wq, mp);
  1043.                 return 0;
  1044.             }
  1045.             else {
  1046.                 stuff = nmp->b_rptr;
  1047.                 size = nmp->b_wptr-nmp->b_rptr;
  1048.             }
  1049.  
  1050.             if ((*info->sInfo.writeIoctl)(info, iocp->ioc_cmd, 
  1051.                          size, stuff, &found))
  1052.             {
  1053.                 mp->b_datap->db_type = M_IOCACK;
  1054.                 iocp->ioc_rval = 0;
  1055.                 qreply(wq, mp);
  1056.                 return 0;
  1057.             }
  1058.             else if (found) {
  1059.                 iocp->ioc_error = EINVAL;
  1060.                 iocp->ioc_rval =    -1;
  1061.                 mp->b_datap->db_type = M_IOCNAK;
  1062.                 qreply(wq,mp);
  1063.                 return 0;
  1064.             }
  1065.             /* FALL THROUGH TO "default" case */
  1066.         }
  1067.         default:
  1068.             break;
  1069.     }
  1070.     if ( canput( wq->q_next ) )
  1071.         putnext(wq, mp);
  1072.     else 
  1073.         freemsg(mp);
  1074.     return 0;
  1075. }
  1076.